<?php

namespace App\Services\Oauth\Oauth2;

use App\Core\Utils\TwHelper\Random;
use App\Models\Oauth\AppModel;
use App\Models\Oauth\CodeModel;
use App\Services\Oauth\Oauth2\Base;
use Illuminate\Support\Facades\Redis;
use App\Exceptions\Response\Service\ServiceCode;
use App\Exceptions\Response\Service\ServiceException;

/**
 * 应用信息（App）和授权码的处理
 * 授权码的获取和生成等相关处理
 */
class App extends Base
{
    //授权码 code的有效期，有效期 20分钟，
    //通常设为10分钟，客户端只能使用该码一次，否则会被授权服务器拒绝。
    const TEN_MINUTE = 1200;

    protected $code;//对应tw_password_code 中的code字段
    protected $app_key;//app_key,对应tw_open_app里面的app_key字段
    protected $app;//应用的信息（app_key、app_secret、name、detail、member_id、domain、status等）
    protected $code_data;//对应tw_password_code 中的code_data字段
    protected $scope;//表示申请的权限范围，(basic)

    public function __construct()
    {
        $this->scope = array('basic', 'userInfo', 'signIn'); //初始化作用域
        parent::__construct();
    }

    public function setAppKey($appKey)
    {
        $this->app_key = $appKey;
    }

    /**
     * 查询app的信息(第3方应用申请的证书) tw_open_app 表
     * 包括(app_key、app_secret、name、detail、domain、status、)
     */
    public function getAppInfo()
    {
        if (!$this->app) {
            //查询app相关的信息
            $client = AppModel::getAppByAppKey($this->app_key);
            if (!$client) {
                throw new ServiceException(ServiceCode::SERVICE_OAUTH_APP_KEY_NOT_EXIST, '', []);
            }
            $this->app = $client;
        }
        return $this->app;
    }

    /**
     * 第3方用户申请授权的应用信息，
     * 应用的信息（app_key、app_secret、name、detail、member_id、domain、status等）
     */
    public function read($attr)
    {
        if (!$this->app[$attr]) {
            throw new ServiceException(ServiceCode::SERVICE_OAUTH_VALUE_NOT_EXIST, '', []);
        }
        return $this->app[$attr];
    }

    /**
     * 获得code
     * 没有就创建并保存到数据库（tw_password_code），有效期是10个小时
     * code_data 包括（userId、app_key、scope、redirect_uri、response_type、time）
     */
    public function getCode()
    {
        if (!$this->code) {
            //不存在code的时候，重新构建code相关数据,保存到数据库（tw_password_code
            $this->code_data['time'] = Random::getUniqid();
            $redirect_uri = $this->code_data['redirect_uri'];

            $app_key = $this->read('app_key');
            $app_secret = $this->read('app_secret');
            //生成code
            $this->code = $this->makeCode($app_key, $redirect_uri, $app_secret, $this->code_data['time']);
            //存储code到数据库tw_password_code
            CodeModel::addCode($this->code, $this->code_data, time() + self::TEN_MINUTE);
            //Redis::set($this->code, $this->code_data);
        }
        return $this->code;
    }

    /**
     * 生成code，4个参数（app_key、redirect_uri、app_secret、time）
     */
    public function makeCode($app_key, $redirect_uri, $app_secret, $time)
    {
        $keyArr = array(
            'app_key' => $app_key,
            'redirect_uri' => $redirect_uri,
            'app_secret' => $app_secret,
            'time' => $time
        );
        $str = implode(',', $keyArr);
        return md5($str);

    }

    public function setCode($code)
    {
        $this->code = $code;
        return $this;
    }

    /**
     * 查询code_data的相关信息(tw_passport_code表的code_data字段)
     * 包括（userId、app_key、scope、redirect_uri、response_type、time、state）
     */
    public function getCodeData()
    {
        if (!$this->code_data) {
            $this->code_data = CodeModel::getCode($this->code);
        }
        return $this->code_data;
    }

    /**
     * 清空授权码 code 的 code_data
     */
    public function deleteCodeData()
    {
        $this->code_data = '';
        // Redis::set($this->code, null);
    }

    /**
     * 验证app_key
     */
    public static function checkApp($appKey)
    {
        //查询app相关的信息
        $client = AppModel::getAppByAppKey($appKey);
        if (!$client) {
            throw new ServiceException(ServiceCode::SERVICE_OAUTH_APP_KEY_NOT_EXIST, '', []);
        }
        return $client;
    }
}